package com.dyh.quickdemozwei.deliver;

import com.alibaba.fastjson.JSON;

import java.util.*;
import java.util.function.Function;

public  class BaseTable<T> implements Cloneable{

  public enum SEARCH{
      ANY
  }

  public static class Row<T> implements Cloneable{
        String[] tags;
        T val;

      @Override
      public Object clone() throws CloneNotSupportedException {
          Row<T> res = (Row)super.clone();
          res.tags = Arrays.copyOf(this.tags,this.tags.length);
          res.val = this.val;
          return res;
      }

      public String getKey(){
          return gentKeys(tags);
      }

      public Row() {
      }

      public Row(String[] tags, T val) {
            this.tags = tags;
            this.val = val;
        }

        public String[] getTags() {
            return tags;
        }

        public void setTags(String[] tags) {
            this.tags = tags;
        }

      public T getVal() {
          return val;
      }

      public void setVal(T val) {
          this.val = val;
      }
  }

   protected Map<String,Row<T>> datas;

    public Map<String, Row<T>> getDatas() {
        return datas;
    }

    public BaseTable() {
        this.datas = new HashMap<>();
    }

   static String gentKeys(int l, String... strArr){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i <l; i++) {
            sb.append(strArr[i]).append("#");
        }
        return sb.substring(0,sb.length()-1);
    }

    static String gentKeys(String... strArr){
       return gentKeys(strArr.length,strArr);
    }


    @Override
    public Object clone()   {
        try {
            BaseTable<T> res = (BaseTable)super.clone();
            res.datas = new HashMap<>();//must

            for (Map.Entry<String, Row<T>> entry : this.datas.entrySet()) {
                res.datas.put(entry.getKey(), (Row<T>) entry.getValue().clone());
            }
            return res;
        }
        catch (Exception ex){

        }


        return null;

    }

    public void set(T val,String...args){


//        String[] tags = new String[args.length];
//        StringBuilder sb = new StringBuilder();
//        for (int i = 0; i < args.length; i++) {
//            tags[i]=args[i].toString();
//            sb.append(args[i]).append("#");
//        }
//        String key = sb.substring(0,sb.length()-1);

        String key = gentKeys(args);
        Row<T> row = new Row<>(args,val);



        datas.put(key,row);
    }

    public   T getVal(String...args){
        Row<T> row = getRow(args);
        if (row==null)
            return null;
        return row.getVal();
    }

    public Row<T> getRow(String...args){
        String key = gentKeys(args);
        Row<T> row = datas.get(key);
        return row;
    }


   <R> List<R> searchCore(Function<Map.Entry<String, Row<T>>,R> mp, Object...args){
       List<R> res = new ArrayList<>();

        for (Map.Entry<String, Row<T>> entry : this.datas.entrySet()) {
            Row<T> row = entry.getValue();

            boolean match = true;
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof SEARCH){
                    if (args[i].equals(SEARCH.ANY))
                        continue;
                }
                try {
                    if (! row.getTags()[i].equals(args[i])){
                        match = false;
                        break;
                    }
                } catch (Exception e) {
                    System.out.println(e);
                    System.out.println(String.format("参数 %s %s ",i ,JSON.toJSONString(row.getTags()[0])));
                }
            }

            if (match){
                res.add(mp.apply(entry));
            }

        }

        return res;
    }

    public List<Map.Entry<String, Row<T>>> searchEntry(Object...args) {
        return searchCore(Function.identity(),args);
    }


    public List< Row<T>> searchRow(Object...args) {
        return searchCore(Map.Entry::getValue,args);
    }






}
